package com.woniu.account.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.woniu.account.dto.Coach.CoachDto;
import com.woniu.account.model.Coach;
import com.woniu.account.dao.CoachDao;
import com.woniu.account.param.User.UpdateNickNameParam;
import com.woniu.account.param.coach.CoachLoginParam;
import com.woniu.account.param.coach.CoachRegisterParam;
import com.woniu.account.param.coach.PageCoachParam;
import com.woniu.account.param.coach.UpdateCoachParam;
import com.woniu.account.service.CoachService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniu.exception.userexp.YogaException;
import com.woniu.util.RedisKeyUtil;
import com.woniu.util.RedisUtil;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 杜岷芫
 * @since 2024年07月11日
 */
@Service
public class CoachServiceImpl extends ServiceImpl<CoachDao, Coach> implements CoachService {

    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private CoachDao coachDao;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private RedissonClient redissonClient;

    @Override
    public void sendRegisterCode(String mobile) throws Exception {
        //判断手机号码是否在一分钟内是否发送短信
        if (redisUtil.hasKey(RedisKeyUtil.registerCodeOnMinute(mobile))) {
            throw new YogaException(500, "1分钟不能再次发送");
        }
        //判断该手机号码在一小时内的短信发送次数
        if (redisUtil.hasKey(RedisKeyUtil.sendNumbers(mobile))) {
            Integer number = Integer.parseInt(redisUtil.get(RedisKeyUtil.sendNumbers(mobile)));
            if (number >= 5) {
                throw new YogaException(500, "超过发送短信次数,请稍后再试");
            }
        }
        //判断手机号是否注册过
        QueryWrapper<Coach> wrapper = new QueryWrapper<>();
        wrapper.eq("coach_phone", mobile);

        Coach coach = coachDao.selectOne(wrapper);

        if (coach != null) {
            throw new YogaException(500, "该手机号已注册");
        }
        //将手机号码保存到消息队列中
        rabbitTemplate.convertAndSend("register_coach_phone_queue", mobile);
    }

    @Override
    public void CodeRegister(CoachRegisterParam param) throws Exception{
//创建一把手机号码锁(公平锁)
        RLock phoneLock = redissonClient.getFairLock(RedisKeyUtil.lockRegisterByCoachPhone(param.getCoachPhone()));
        //创建一把用户名锁（公平锁）
        RLock userNameLock = redissonClient.getFairLock(RedisKeyUtil.lockRegisterByCoachname(param.getCoachName()));
        //变成多资源锁；这里放进该方法的顺序就是加锁的顺序
        RLock lock = redissonClient.getMultiLock(phoneLock, userNameLock);

        if (lock.tryLock(10, TimeUnit.SECONDS)) {
            //设置10秒；代表成功
            try {//一定要用try块包括成功，finally成功与否都要释放锁
                //判断手机号是否注册过
                QueryWrapper<Coach> wrapper = new QueryWrapper<Coach>();
                wrapper.eq("coach_phone", param.getCoachPhone());

                Coach coach = coachDao.selectOne(wrapper);
                if (coach != null) {
                    throw new Exception("该手机号已注册");
                }
                //判断用户名是否已经被注册
                QueryWrapper<Coach> wrapper1 = new QueryWrapper<Coach>();
                wrapper1.eq("coach_name", param.getCoachName());
                Coach coach1 = coachDao.selectOne(wrapper1);
                if (coach1 != null) {
                    throw new Exception("用户名已注册");
                }
                //执行注册
                coach = BeanUtil.toBean(param, Coach.class);
                //对密码加密
                String md5 = String.valueOf(DigestUtil.md5Hex(param.getCoachPassword()));
                coach.setCoachPassword(md5);
                coachDao.insert(coach);
                //删除验证码
                redisUtil.delete(RedisKeyUtil.registerCodeKey(param.getCoachPhone()));
            } finally {
                lock.unlock();//释放锁
            }

        } else {
            //代表失败
            throw new Exception("服务器繁忙");
        }
    }

    @Override
    public CoachDto login(CoachLoginParam param) {
        QueryWrapper<Coach> wrapper = new QueryWrapper<>();
        wrapper.eq("coach_phone", param.getCoachPhone());
        Coach coach = coachDao.selectOne(wrapper);
        if (coach == null) {
            throw new YogaException(5002,"尚未注册");
        }
        if (!coach.getCoachPassword().equals(DigestUtil.md5Hex(param.getCoachPassword())) ){
            throw new YogaException(5005,"密码错误");

        }
        return BeanUtil.toBean(coach, CoachDto.class);
    }

    @Override
    public PageInfo<CoachDto> pageAllCoach(PageCoachParam param) {
        PageHelper.startPage(param.getPageNum() == null ? 1 : param.getPageNum(), param.getPageSize() == null ? 6 : param.getPageSize());
        QueryWrapper<Coach> qw = new QueryWrapper<Coach>().like("coach_name", param.getCoachName());
        List<Coach> coaches = coachDao.selectList(qw);
        PageInfo<Coach> coachPageInfo = new PageInfo<>(coaches);
        PageInfo<CoachDto> coachDtoPageInfo = new PageInfo<>();
        coachDtoPageInfo.setList(BeanUtil.copyToList(coachPageInfo.getList(), CoachDto.class));
        coachDtoPageInfo.setPageNum(coachPageInfo.getPageNum());
        coachDtoPageInfo.setPageSize(coachPageInfo.getPageSize());
        coachDtoPageInfo.setPages(coachPageInfo.getPages());
        coachDtoPageInfo.setTotal(coachPageInfo.getTotal());
        return coachDtoPageInfo;
    }

    @Override
    public CoachDto updateCoach(UpdateCoachParam param) {

        return null;
    }
}
